package com.atguigu.tingshu.account.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.account.mapper.RechargeInfoMapper;
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
import com.atguigu.tingshu.account.service.MqOpsService;
import com.atguigu.tingshu.account.service.UserAccountService;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.model.account.RechargeInfo;
import com.atguigu.tingshu.model.account.UserAccount;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;

@Service
@Slf4j
public class MqOpsServiceImpl implements MqOpsService {
    @Autowired
    private UserAccountMapper userAccountMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserAccountService userAccountService;

    @Autowired
    private RechargeInfoMapper rechargeInfoMapper;


    @Override
    public void userAccountRegister(String content) {
        try {

            UserAccount userAccount = new UserAccount();
            userAccount.setUserId(Long.parseLong(content));
            int insert = userAccountMapper.insert(userAccount);
            log.info("初始化用户余额：{}",insert > 0 ? "success" : "fail");
        }catch (NumberFormatException e){
            throw new GuiguException(201,"服务内部数据处理失败");
        }

    }

    @Override
    public void listenUserAccountUnlock(String orderNo) {
        //修改 lock_amount(-) avaliable_amount(+)
        String dataKey = "user:account:amount" + orderNo;
        String lockKey = "user:account:amount:lock:retry" + orderNo;
        String lockAmountResultStr = redisTemplate.opsForValue().get(dataKey);

        if (StringUtils.isEmpty(lockAmountResultStr)){
            return;
        }
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(lockAmountResultStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        String content = accountLockResultVo.getContent();
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockKey, "1");
        if (aBoolean){
            //2.解锁
            try {
                int count = userAccountMapper.unLock(userId,amount);
                //3.解锁记录存放到流水表中
                userAccountService.log(userId,amount,"解锁：" +content,orderNo,"1203");
                //4.删除缓存中的锁定对象
                redisTemplate.delete(dataKey); // 正常干完活才能删除缓存标识key
            }catch (Exception e){
                throw new GuiguException(201,"解锁失败");
            }finally {
                redisTemplate.delete(lockKey);//不管正常还是异常都要把锁key删掉
            }

        }

    }

    @Override
    public void listenUserAccountMinus(String orderNo) {
        //修改 lock_amount(-) total_amount(-)
        String dataKey = "user:account:amount" + orderNo;
        String lockKey = "user:account:minus:lock" + orderNo;
        String lockAmountResultStr = redisTemplate.opsForValue().get(dataKey);

        if (StringUtils.isEmpty(lockAmountResultStr)){
            return;
        }
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(lockAmountResultStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        String content = accountLockResultVo.getContent();
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockKey, "1");
        if (aBoolean){
            //2.解锁
            try {
                int count = userAccountMapper.minus(userId,amount);
                //3.解锁记录存放到流水表中
                userAccountService.log(userId,amount,"消费：" +content,orderNo,"1204");
                //4.删除缓存中的锁定对象
                redisTemplate.delete(dataKey);
            }catch (Exception e){
                throw new GuiguException(201,"消费失败");
            }finally {
                redisTemplate.delete(lockKey);
            }
        }



    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void userAccountOpsRecharge(String userId, String orderNo) {

        //1.根据订单编号以及用户Id查询零钱对象
        RechargeInfo rechargeInfo = rechargeInfoMapper.selectOne(
                new LambdaQueryWrapper<RechargeInfo>()
                        .eq(RechargeInfo::getOrderNo, orderNo)
                        .eq(RechargeInfo::getUserId, userId));
        if (rechargeInfo == null){
            return;
        }
       //2.修改零钱订单状态
        int count = rechargeInfoMapper.updateRechargeStatus(userId,orderNo);
        log.info("修改零钱订单状态：{}",count > 0 ? "success" : "fail");


        //3.修改用户账户余额信息
        int count1 = userAccountMapper.updateUserAccount(userId,rechargeInfo.getRechargeAmount());
        log.info("修改用户账户信息：{}",count1 > 0 ? "success" : "fail");

        //4.记录用户账户的流水
        userAccountService.log(Long.parseLong(userId),rechargeInfo.getRechargeAmount(),"充值："+rechargeInfo.getRechargeAmount(),orderNo,"1201");
    }
}
